package com.gitee.wsl.platform.thread.task

import com.gitee.wsl.platform.thread.task.TaskExecutors.unlimitedThreadPoolForIO
import com.gitee.wsl.platform.thread.task.VirtualThreads.areVirtualThreadsSupported
import com.gitee.wsl.platform.thread.task.VirtualThreads.executorService
import com.gitee.wsl.platform.thread.task.VirtualThreads.factory
import com.gitee.wsl.platform.thread.task.VirtualThreads.isVirtualThread
import java.util.concurrent.CountDownLatch
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicReference
import kotlin.test.Test
import kotlin.test.assertFalse
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
import kotlin.test.fail


class LoomTest {
    @Test
    @Throws(InterruptedException::class)
    fun commonPoolInJava21() {
        assertTrue(areVirtualThreadsSupported(),"Requires Java 21+")

        val commonPool = unlimitedThreadPoolForIO("tasks-io")
        try {
            val latch: CountDownLatch = CountDownLatch(1)
            val isVirtual: AtomicBoolean = AtomicBoolean(false)
            val name = AtomicReference<String>()

            commonPool.execute {
                isVirtual.set(isVirtualThread(Thread.currentThread()))
                name.set(Thread.currentThread().name)
                latch.countDown()
            }

            TimedAwait.latchAndExpectCompletion(latch)
            assertTrue(isVirtual.get(), "isVirtual")
            assertTrue(
                name.get().matches("tasks-io-virtual-\\d+".toRegex()),
                "name.matches(\"tasks-io-virtual-\\\\d+\")"
            )
        } finally {
            commonPool.shutdown()
        }
    }

    @Test
    @Throws(InterruptedException::class, VirtualThreads.NotSupportedException::class)
    fun canInitializeFactoryInJava21() {
        assertTrue(areVirtualThreadsSupported(), "Requires Java 21+")

        val f = factory("my-vt-")
        assertNotNull(f)

        val latch: CountDownLatch = CountDownLatch(1)
        val isVirtual: AtomicBoolean = AtomicBoolean(false)
        val name = AtomicReference<String>()

        f.newThread {
            isVirtual.set(isVirtualThread(Thread.currentThread()))
            name.set(Thread.currentThread().name)
            latch.countDown()
        }.start()

        TimedAwait.latchAndExpectCompletion(latch)
        assertTrue(isVirtual.get(), "isVirtual")
        assertTrue(
            name.get().matches("my-vt-\\d+".toRegex()),
            "name.matches(\"my-vt-\\\\d+\")"
        )
    }

    @Test
    @Throws(InterruptedException::class, VirtualThreads.NotSupportedException::class)
    fun canInitializeExecutorInJava21() {
        assertTrue(areVirtualThreadsSupported(), "Requires Java 21+")

        val executor = executorService("my-vt-")
        assertNotNull(executor, "executor")
        try {
            val latch: CountDownLatch = CountDownLatch(1)
            val isVirtual: AtomicBoolean = AtomicBoolean(false)
            val name = AtomicReference<String>()
            executor.execute {
                isVirtual.set(isVirtualThread(Thread.currentThread()))
                name.set(Thread.currentThread().name)
                latch.countDown()
            }

            TimedAwait.latchAndExpectCompletion(latch)
            assertTrue(isVirtual.get(), "isVirtual")
            assertTrue(
                name.get().matches("my-vt-\\d+".toRegex()),
                "name.matches(\"my-vt-\\\\d+\")"
            )
        } finally {
            executor.shutdown()
        }
    }

    @Test
    fun cannotInitializeLoomUtilsInOlderJava() {
        val r = SysProp.Companion.withVirtualThreads(false)
        try {
            try {
                factory("tasks-io")
                fail("Should throw")
            } catch (ignored: VirtualThreads.NotSupportedException) {
            }
            try {
                executorService("tasks-io").shutdown()
                fail("Should throw")
            } catch (ignored: VirtualThreads.NotSupportedException) {
            }
        } finally {
            r.close()
        }
    }

    @Test
    @Throws(InterruptedException::class)
    fun commonPoolInOlderJava() {
        val r = SysProp.Companion.withVirtualThreads(false)
        val commonPool = unlimitedThreadPoolForIO("tasks-io")
        try {
            assertFalse(areVirtualThreadsSupported(), "areVirtualThreadsSupported")
            assertNotNull(commonPool, "commonPool")

            val latch: CountDownLatch = CountDownLatch(1)
            val isVirtual: AtomicBoolean = AtomicBoolean(true)
            val name = AtomicReference<String>()

            commonPool.execute {
                isVirtual.set(isVirtualThread(Thread.currentThread()))
                name.set(Thread.currentThread().name)
                latch.countDown()
            }

            TimedAwait.latchAndExpectCompletion(latch)
            assertFalse(isVirtual.get(), "isVirtual")
            assertTrue(
                name.get().matches("^tasks-io-platform-\\d+$".toRegex()),
                "name.matches(\"^tasks-io-platform-\\\\d+$\")"
            )
        } finally {
            r.close()
            commonPool.shutdown()
        }
    }
}
